/*
 * Composition Knowledge Miner. A data mashup composition knowledge miner
 * Copyright (C) 2011 Carlos Rodriguez
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

package eu.ict_omelette.mashup.compositionminer;

import eu.ict_omelette.mashup.canonicalmodel.CanonicalMashup;
import eu.ict_omelette.mashup.canonicalmodel.Component;
import eu.ict_omelette.mashup.canonicalmodel.Dataflow;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;

/**
 *
 * @author carlos
 */
public class ConnectorCoOccurrencePattern {
    private LinkedList<CanonicalMashup> compRepo;

    public ConnectorCoOccurrencePattern(LinkedList<CanonicalMashup> compRepo){
        this.compRepo = compRepo;        
    }

    public List<CanonicalMashup> mine(Double minSupDf, Double minSupDm){
        LinkedList<CanonicalMashup> result = new LinkedList();

        Iterator<CanonicalMashup> repoIt = this.compRepo.iterator();
        LinkedHashMap<String, Integer> tripletSupport = new LinkedHashMap();

        // In the following code we try to identify triplets of connected components
        // of the form A=>B=>C
        while(repoIt.hasNext()){            
            LinkedHashMap<String, String> tripletInMashup = new LinkedHashMap();

            //In the following we get all the triplets of components that appear
            //in a composition
            CanonicalMashup cm = repoIt.next();
            Iterator<Component> itComp = cm.getComponents();
            while(itComp.hasNext()){
                Component midComp = itComp.next();

                Iterator<Dataflow> dfIt1 = cm.getDataFlows();
                while(dfIt1.hasNext()){
                    Dataflow df1 = dfIt1.next();
                    Component fromComp1 = df1.getFromComponent();
                    Component toComp1 = df1.getToComponent();

                    if(!fromComp1.getId().equals(midComp.getId()))
                        continue;

                    Iterator<Dataflow> dfIt2 = cm.getDataFlows();
                    while(dfIt2.hasNext()){
                        Dataflow df2 = dfIt2.next();
                        Component toComp = df2.getToComponent();

                        if(!toComp.getId().equals(midComp.getId()))
                            continue;

                        Component fromComp2 = df2.getFromComponent();
                        String triplet = fromComp2.getType() + "." + df2.getFromPort() + "=>" +
                                df2.getToPort() + "." + midComp.getType() + "." + df1.getFromPort() +
                                "=>" + df1.getToPort() + "." + toComp1.getType();
                        

                        tripletInMashup.put(triplet, triplet);
                    }
                }
            }

            //Here we take the triplets that appear in a composition and
            //incresead the support of each triplet in the global hash of triplets
            Iterator<String> it1 = tripletInMashup.keySet().iterator();
            while(it1.hasNext()){
                String key = it1.next();

                Integer supp = tripletSupport.get(key);
                if(supp == null){
                    tripletSupport.put(key, 1);
                }else{
                    tripletSupport.put(key, supp + 1);
                }
            }

        }

        Iterator<String> it2 = tripletSupport.keySet().iterator();
        while(it2.hasNext()){
            String key = it2.next();

            Integer supp = tripletSupport.get(key);
            double relSupp = (double)supp / (double)compRepo.size();            

            if(relSupp >= minSupDf){
                CanonicalMashup cm = new CanonicalMashup();
                
                cm.setId("");
                cm.setName("");
                cm.setSrc("");

                String[] comps = key.split("=>");

                Component leftComp = new Component();
                String strLeftComp = comps[0];
                String[] pairL = strLeftComp.split("\\.");
                String lCompName = pairL[0];
                String lPortName = pairL[1];                
                leftComp.setId("");
                leftComp.setIsEmbedding(false);
                leftComp.setName(lCompName);
                leftComp.setType(lCompName);

                Component midComp = new Component();
                String strMidComp = comps[1];
                String[] tripletM = strMidComp.split("\\.");
                String mCompName = tripletM[1];
                String mIPortName = tripletM[0];
                String mOPortName = tripletM[2];
                midComp.setId("");
                midComp.setIsEmbedding(false);
                midComp.setName(mCompName);
                midComp.setType(mCompName);

                Dataflow lDf = new Dataflow();
                lDf.setFromPort(leftComp, lPortName);
                lDf.setToPort(midComp, mIPortName);

                Component rightComp = new Component();
                String strRightComp = comps[2];
                String[] pairR = strRightComp.split("\\.");
                String rCompName = pairR[1];
                String rPortName = pairR[0];
                rightComp.setId("");
                rightComp.setIsEmbedding(false);
                rightComp.setName(rCompName);
                rightComp.setType(rCompName);

                Dataflow rDf = new Dataflow();
                rDf.setFromPort(midComp, mOPortName);
                rDf.setToPort(rightComp, rPortName);

                cm.addComponent(leftComp);
                cm.addComponent(midComp);
                cm.addComponent(rightComp);

                cm.addDataflow(lDf);
                cm.addDataflow(rDf);

                result.add(cm);
            }
        }

        return result;
    }
}
